gusucode.com > VC++ 图片浏览器的设计与实现+设计文档源码程序 > VC++ 图片浏览器的设计与实现+设计文档源码程序/code/PictView/ImageTga.cpp
//Download by http://www.NewXing.com #include "stdafx.h" #include "ClassImage.h" #include "stdio.h" static BYTE * RLE_TGA_DecodeLine(BYTE * InBuffer,int iColorBit,int iNumPixel,BYTE * OutBuffer) { register BYTE Data; register int Num; iColorBit = (iColorBit + 7) / 8; while(iNumPixel > 0) { Data = *InBuffer++; if((Data & 0x80) == 0x80) { Num = (Data & 0x7F) + 1; iNumPixel -= Num; for(int i=0; i<Num; ++i,OutBuffer += iColorBit) memcpy(OutBuffer,InBuffer,iColorBit); InBuffer += iColorBit; } else { Num = ++Data; iNumPixel -= Num; Num *= iColorBit; memcpy(OutBuffer,InBuffer,Num); OutBuffer += Num; InBuffer += Num; } } return InBuffer; } static BYTE * RLE_TGA_EncodeLine(const BYTE * InBuffer, int iColorBit, int iNumPixel, BYTE * OutBuffer) { DWORD Data, Next ; const BYTE * pBak ; register DWORD Count ; iColorBit = (iColorBit + 7) / 8 ; // 转换为字节数 while (iNumPixel > 0) { pBak = InBuffer ; // 记数指针 memcpy (&Data, InBuffer, iColorBit) ; // 第一个像素 InBuffer += iColorBit ; iNumPixel-- ; Count = 1 ; while ((Count < 0x7F) && (iNumPixel > 0)) // 统计重复像素 { memcpy (&Next, InBuffer, iColorBit) ; // 下一个像素 if (Next != Data) break ; InBuffer += iColorBit ; iNumPixel-- ; Count++ ; } if (Count == 1) // 无重复像素 { while ((Count < 0x7F) && (iNumPixel > 0)) // 统计不重复像素 { Count++ ; Data = Next ; InBuffer += iColorBit ; iNumPixel-- ; memcpy (&Next, InBuffer, iColorBit) ; // 下一个像素 if (Data == Next) break ; } // 直接copy不重复像素 *OutBuffer++ = (BYTE)(Count - 1) ; Count = InBuffer - pBak ; // Count->临时变量 memcpy (OutBuffer, pBak, Count) ; OutBuffer += Count ; } else // 重复像素 { *OutBuffer++ = 0x80 | (BYTE)--Count ; memcpy (OutBuffer, &Data, iColorBit) ; OutBuffer += iColorBit ; } } // End of while return OutBuffer ; } #pragma pack(push,1) typedef struct tagTGAHEAD { BYTE byID_Length; //本结构体大小 BYTE byPalType; //调色板类型:0无调色板,1有调色板 BYTE byImageType; //01 UC+PAL,02 UC+NP 03 UC+BW,09 RLE+PAL,0A RLE+NP 0B RLE+BW WORD wPalFirstNdx; //调色板其始索引 WORD wPalLength; //调色板长度 BYTE byPalBits; //调色板中每一颜色占用的位数 WORD wLeft;//X WORD wBottom;//X WORD wWidth; WORD wHeight; BYTE byColorBits; BYTE desc; }TGAHEAD, *PTGAHEAD; typedef struct tagTGAFooter { long ext_area; long dev_area; char signature[18]; //"TRUEVISION-XFILE" }TGAFooter; #pragma pack(pop) BOOL LanImage::ReadTga(LPBYTE pFileBuffer,UINT nFileSize,int ndegree) { TGAHEAD * ph = (TGAHEAD *)pFileBuffer; TGAFooter * pf = (TGAFooter *)(pFileBuffer + nFileSize - 26); if(ph->byColorBits ==15) //16位色555格式,应该将byCorlorBits置为16. ph->byColorBits = 16; //判断是否正是一个TGA图 // if(strncmp(pf->signature,"TRUEVISION-XFILE",16) != 0) // { // delete [] pFileBuffer; // return FALSE; // } if(FALSE == Create(ph->wWidth,ph->wHeight,ph->byColorBits,ndegree)) return FALSE; if(ph->byID_Length == 0) ph->byID_Length = sizeof(TGAHEAD); BYTE * pCurr = pFileBuffer + ph->byID_Length; DWORD dwPicth = ph->wWidth * ph->byColorBits / 8; //一行图象数据的长度 //读调色板 if(ph->byPalType == 1) { if(ph->byPalBits == 24 || ph->byPalBits == 32) { for(int i=ph->wPalFirstNdx; i<ph->wPalFirstNdx + ph->wPalLength; ++i) { m_pPal[i].rgbBlue = *pCurr++; m_pPal[i].rgbGreen = *pCurr++; m_pPal[i].rgbRed = *pCurr++; if(ph->byPalBits == 32) m_pPal[i].rgbReserved = *pCurr++; else m_pPal[i].rgbReserved = 0; } } else { return FALSE; } } //解码图象数据 if(ph->byImageType & 0x08) //压缩 { if(UC_SWAP_HEIGHT(ph->desc & 0x20)) //上下颠倒 { BYTE * pOut = GetLine(m_nHeight - 1); for(int i=0; i<ph->wHeight; ++i, pOut -= m_nPitch) pCurr = RLE_TGA_DecodeLine(pCurr,ph->byColorBits,ph->wWidth,pOut); } else { BYTE * pOut = GetLine(0); for(int i=0; i<ph->wHeight; ++i, pOut += m_nPitch) pCurr = RLE_TGA_DecodeLine(pCurr,ph->byColorBits,ph->wWidth,pOut); } } else//未压缩 { if(UC_SWAP_HEIGHT(ph->desc & 0x20)) //上下颠倒 { BYTE * pOut = GetLine(m_nHeight - 1); for(int i=0; i<ph->wHeight; ++i, pCurr += dwPicth, pOut -= m_nPitch) memcpy(pOut,pCurr,dwPicth); } else { BYTE * pOut = GetLine(0); for(int i=0; i<ph->wHeight; ++i, pCurr += dwPicth, pOut += m_nPitch) memcpy(pOut,pCurr,dwPicth); } } return TRUE; } //UINT VPIC_API vpic_WriteTGA(const VPicture & pic,BYTE * pStart,VP_LAYER_INFO * pLayerInfo,UINT uFlags) BOOL LanImage::SaveTga(LPCTSTR pszFileName) const { CFile file; if(FALSE == file.Open(pszFileName,CFile::modeCreate | CFile::modeWrite)) return FALSE; TGAHEAD th; TGAFooter tf; tf.ext_area = tf.dev_area = 0; strcpy(tf.signature,"TRUEVISION-XFILE"); memset(&th,0,sizeof(th)); if(GetBitCount() <= 8) { th.byPalType = 1; th.wPalLength = 1 << GetBitCount(); th.byPalBits = 32; th.byImageType = 1; } else th.byImageType = 2; th.desc = 0; th.wWidth = this->GetWidth(); th.wHeight = this->GetHeight(); th.byColorBits = this->GetBitCount(); // 写文件头 file.Write(&th,sizeof(th)); // 写调色板 if(th.byPalType) { file.Write(this->GetPalette(),sizeof(RGBQUAD) * (1 << this->GetBitCount())); } // 写图象数据 int height = th.wHeight; int length = th.wWidth * th.byColorBits / 8; for(int y=0;y<height;++y) file.Write(GetLine(y),length); // 写信息尾 file.Write(&tf,sizeof(tf)); return TRUE; }